
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include "Common.hpp"
#include <unordered_map>
#include <fstream>
using namespace std;
using namespace LogModule;

const string Sep = "\r\n";
const string Blank_line = Sep;
const string LineSep = " ";      // 属性空格分割符
const string HeadLineSep = ": "; // 头部分割符
const string defaulthomepage = "wwwroot";
const string http_version = "HTTP/1.0";
const string page404 = "wwwroot/404.html";
const string firstpage = "index.html";

class HttpRequest
{
public:
    HttpRequest()
        : _version(http_version),
          _isexec(false)
    {
    }
    ~HttpRequest() {}

    bool IsHasArgs()
    {
        return _isexec;
    }
    // Host: 42.194.139.95:8082
    // Connection: keep-alive
    // User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0
    // Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
    // Referer: http://42.194.139.95:8082/
    // Accept-Encoding: gzip, deflate
    // Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
    bool ParseHeaderkv()
    {
        string key, value;
        for (auto &header : _req_header)
        {
            if (SplitString(header, HeadLineSep, &key, &value)) // 根据分隔符拆成key value
            {
                _head_kv.insert(make_pair(key, value));
            }
        }
        return true;
    }

    bool ParseHeader(string &request_str)
    {
        // 剩余部分先放进vector,再逐一解析
        string line;
        while (true)
        {
            bool r = ParseOneLine(request_str, &line, Sep);
            if (r && !line.empty())
            {
                _req_header.push_back(line);
            }
            else if (r && line.empty()) // 读到空行
            {
                _blank_line = Sep;
                break;
            }
            else // 解析失败
            {
                return false;
            }
        }
        ParseHeaderkv();
        return true;
    }

    void Deserialize(string &request_str)
    {
        // 处理报头
        if (ParseOneLine(request_str, &_req_line, Sep)) // 第一行
        {                                               // 提取请求行中的详细字段
            ParseReqLine(_req_line, LineSep);
            ParseHeader(request_str);

            // 此时reque_str剩下的内容就是正文
            _body = request_str;
            LOG(LogLevel::DEBUG) << "body: " << _body << "\n";
            // 分析请求中是否有参数：
            if (_method == "POST")
            {
                _isexec = true;
                _args = _body; // POST参数放在正文
                _path = _uri;
                LOG(LogLevel::DEBUG) << "POST,path: " << _path << "\n";
                LOG(LogLevel::DEBUG) << "POST,Args: " << _args << "\n";
            }
            else if (_method == "GET")
            {
                auto pos = _uri.rfind('?');
                if (pos != string::npos) // 说明带参 是动态资源
                {
                    _isexec = true;               // login?name=xxx&...
                    _path = _uri.substr(0, pos);  // 拿到问号左边部分，可以用来进行功能路由_route执行上层处理应答方法
                    _args = _uri.substr(pos + 1); // 参数
                    LOG(LogLevel::DEBUG) << "GET,path: " << _path << "\n";
                    LOG(LogLevel::DEBUG) << "GET,Args: " << _args << "\n";
                }
            }
        }
    }

    string Path() { return _path; }
    string Args() { return _args; }

    void Print()
    {
        cout << "method: " << _method << endl;
        cout << "uri: " << _uri << endl;
        cout << "version: " << _version << endl;
        for (auto &kv : _head_kv)
        {
            cout << kv.first << "  # ";
            cout << kv.second << endl;
        }
        cout << "blank_line: " << _blank_line << endl;
        cout << "body: " << _body << endl;
    }

    string Uri()
    {
        return _uri;
    }

    void SetUri(const string newuri)
    {
        _uri = newuri;
    }

    string Suffix() // 请求资源的后缀
    {
        //_uri -> wwwroot/index.html
        auto pos = _uri.rfind("."); // 从后往前
        if (pos == string::npos)
            return string(".html");
        else
            return _uri.substr(pos);
    }

    string GetContent(const string path)
    {
        // 打开文件，以二进制模式读取
        std::ifstream file(path, std::ios::binary);
        if (!file.is_open())
        {
            std::cerr << "无法打开文件: " << path << std::endl;
            return "";
        }

        // 获取文件大小
        file.seekg(0, std::ios::end);
        std::streamsize fileSize = file.tellg();
        file.seekg(0, std::ios::beg);

        // 分配内存并读取文件内容
        std::string fileContent(fileSize, '\0');
        if (!file.read(fileContent.data(), fileSize))
        {
            std::cerr << "读取文件失败: " << path << std::endl;
            return "";
        }

        file.close();       // 关闭文件
        return fileContent; // 返回二进制数据

        // string content;
        // ifstream in(path, ios::binary);
        // if (!in.is_open())
        //     return string();
        // in.seekg(0, in.end);
        // int filesize = in.tellg();
        // in.seekg(0, in.beg);

        // content.resize(filesize);
        // in.read((char *)content.c_str(), filesize);
        // in.close();
        // return content;

        // 暂时做法
        //   string content;
        //   ifstream in(_uri);
        //   if(!in.is_open()) return string();
        //   string line;
        //   while(getline(in,line))
        //   {
        //       content += line;
        //   }
        //   in.close();
        //   return content;
    }

private:
    // GET /favicon.ico HTTP/1.1  ->  GET    /favicon.ico     HTTP/1.1
    void ParseReqLine(string &str, const string Sep)
    {
        stringstream ss(str);
        ss >> _method >> _uri >> _version; // sstringstream按照空格提取
        // _uri = defaulthomepage + _uri;
    }

private:
    string _req_line;
    vector<string> _req_header;
    string _blank_line;
    string _body;    // 有可能包含参数
    string _method;  // 请求方法
    string _uri;     // 请求资源路径  用户真正想要的  //login.html || login?xxx
    string _version; // http版本
    // 在反序列化过程中,细化我们解析出来的字段
    unordered_map<string, string> _head_kv;
    string _path;
    string _args;
    bool _isexec; // 是否要执行
};

// d
class HttpResponse
{
public:
    HttpResponse()
        : _version(http_version),
          _blank_line(Sep)
    {
    }

    ~HttpResponse() {}

    void Build(HttpRequest &req)
    {
        // #define TestRedir
        // #ifdef TestRedir
        //         _status_code = 302; // 临时重定向
        //         _status_desc = Code2Desc(_status_code);
        //         SetHeader("Location", "https://www.qq.com/");
        //         for (auto &header : _head_kv)
        //         {
        //             _resp_header.push_back(header.first + HeadLineSep + header.second);
        //         }
        // #else
        string uri = defaulthomepage + req.Uri();
        if (uri.back() == '/') // 设置/为默认首页
        {
            uri += firstpage; // wwwroot/index.html
            // req.SetUri(uri);
        }

        _content = req.GetContent(uri); // 根据uri构建内容
        if (_content.empty())           // 认为用户请求资源不存在
        {
            _status_code = 404;
            // req.SetUri(page404);
            _content = req.GetContent(page404); // 重新返回404内容
        }
        else
        {
            _status_code = 200;
        }

        string Mime_Type = Suffix2Desc(req.Suffix());
        SetHeader("Content-Type", Mime_Type);

        _status_desc = Code2Desc(_status_code); // 状态码描述

        if (!_content.empty())
        {
            SetHeader("Content-Length", to_string(_content.size()));
        }
        _body = _content;
    }

    void SetCode(int code)
    {
        _status_code = code;
        _status_desc = Code2Desc(code);
    }

    void SetBody(const string &body)
    {
        _body = body;
    }

    void Serialize(string *resp_str)
    {
        for (auto &header : _head_kv)
        {
            _resp_header.push_back(header.first + HeadLineSep + header.second);
        }

        // 填充字段
        _resp_line = _version + LineSep + to_string(_status_code) + LineSep + _status_desc + Sep;

        // 序列化
        *resp_str = _resp_line; // 请求行
        for (auto &line : _resp_header)
        {
            *resp_str += (line + Sep); // 报头
        }
        *resp_str += _blank_line; // 空行
        *resp_str += _body;       // 正文
    }

    void SetHeader(const string &k, const string &v)
    {
        _head_kv[k] = v;
    }

private:
    string Code2Desc(int code)
    {
        switch (code)
        {
        case 200:
            return "OK";
        case 400:
            return "Not Found";
        case 301:
            return "Moved Permanently";
        case 302:
            return "Found";
        default:
            return string();
        }
    }

    // 后缀转描述
    string Suffix2Desc(const string &suffix)
    {
        if (suffix == ".html")
            return "text/html";
        else if (suffix == ".jpg")
            return "application/x.jpg";
        else
            return "text/html";
    }

private:
    // 应答必备要素
    string _version;
    int _status_code;    // 状态码
    string _status_desc; // 状态码描述
    string _content;
    unordered_map<string, string> _head_kv;
    // 最终要这四部分,构建应答
    string _resp_line;
    vector<string> _resp_header;
    string _blank_line;
    string _body;
};
